
/**
 * 通用工具函数集合
 *
 * 本文件包含了项目中常用的工具函数，涵盖：
 * - 日期时间处理
 * - 数据结构操作
 * - 组件动态加载
 * - 分页处理
 * - UI交互辅助
 *
 * @author Vue3 CRM Team
 * @version 1.0.0
 * @since 2024
 */

import moment from 'moment'

/**
 * 工具函数对象
 * 包含项目中所有通用的工具方法
 */
const TOOLS = {
    /**
     * Moment.js 实例
     * 用于高级日期时间处理
     * @type {Object}
     */
    moment,

    /**
     * 扁平化树形数据结构
     * 将具有 children 属性的树形数组转换为一维数组
     *
     * @param {Array} arr - 树形数据数组
     * @returns {Array} 扁平化后的一维数组
     *
     * @example
     * const treeData = [
     *   { id: 1, name: '部门A', children: [{ id: 2, name: '子部门A1' }] },
     *   { id: 3, name: '部门B' }
     * ]
     * const flatData = TOOLS.Flaten(treeData)
     * // 结果: [{ id: 1, name: '部门A', children: [...] }, { id: 2, name: '子部门A1' }, { id: 3, name: '部门B' }]
     */
    Flaten(arr) {
        // 检查输入参数是否为有效数组
        if (!arr || !Array.isArray(arr)) {
            return [];
        }

        return arr.reduce((result, item) => {
            // 将当前项添加到结果中，如果有子项则递归处理
            return result.concat(item, (Array.isArray(item.children) ? TOOLS.Flaten(item.children) : []));
        }, []);
    },
    /**
     * 获取格式化的当前日期时间
     * 支持多种格式输出，主要用于表单默认值和数据查询
     *
     * @param {string} type - 日期格式类型
     *   - 'day': 返回完整日期 YYYY-MM-DD
     *   - 'month': 返回年月 YYYY-MM
     *   - 其他值: 默认返回完整日期
     * @returns {string} 格式化后的日期字符串
     *
     * @example
     * TOOLS.GetTime()        // '2024-03-15' (默认为 day)
     * TOOLS.GetTime('day')   // '2024-03-15'
     * TOOLS.GetTime('month') // '2024-03'
     */
    GetTime(type = 'day') {
        const now = new Date();
        const year = now.getFullYear();
        let month = now.getMonth() + 1; // getMonth() 返回 0-11，需要 +1
        const date = now.getDate();

        // 格式化月份和日期为两位数（补零）
        month = month.toString().padStart(2, "0");
        const formattedDate = date.toString().padStart(2, "0");

        // 根据类型返回不同格式
        if (type === 'day') {
            return `${year}-${month}-${formattedDate}`
        } else if (type === 'month') {
            return `${year}-${month}`
        }

        // 默认返回完整日期格式
        return `${year}-${month}-${formattedDate}`;
    },
    /**
     * 获取最近几个月的月份选项
     * 从当前月份开始，向前推算指定数量的月份
     * 主要用于下拉选择器的选项数据
     *
     * @param {number} count - 要获取的月份数量，默认12个月
     * @returns {Array<string>} 月份字符串数组，格式为 YYYY-MM
     *
     * @example
     * // 假设当前是 2024-03
     * TOOLS.getMonths(3)  // ['2024-03', '2024-02', '2024-01']
     * TOOLS.getMonths()   // 返回最近12个月
     */
    getMonths(count = 12) {
        const months = []
        const now = moment()

        // 从当前月份开始，逐月向前推算
        for (let i = 0; i < count; i++) {
            const monthStr = now.clone().subtract(i, 'months').format('YYYY-MM')
            months.push(monthStr)
        }

        return months
    },

    /**
     * 排行榜前三名图标资源
     * 用于显示排行榜中前三名的特殊图标
     * @type {Array<string>}
     */
    top: [
        "//jzt-scrm.oss-cn-shanghai.aliyuncs.com/rank/1.png", // 第一名图标
        "//jzt-scrm.oss-cn-shanghai.aliyuncs.com/rank/2.png", // 第二名图标
        "//jzt-scrm.oss-cn-shanghai.aliyuncs.com/rank/3.png"  // 第三名图标
    ],
    /**
     * Element Plus 日期选择器快捷选项配置
     * 提供常用的日期范围快捷选择，提升用户体验
     *
     * @type {Array<Object>} 快捷选项数组
     * @property {string} text - 显示文本
     * @property {Function} value - 返回日期范围的函数 [startDate, endDate]
     *
     * @example
     * // 在 el-date-picker 中使用
     * <el-date-picker :shortcuts="TOOLS.DatePickerShortcuts" />
     */
    DatePickerShortcuts: [
        {
            text: '今日',
            value: () => {
                const start = new Date() // 今天开始时间
                const end = new Date()   // 今天结束时间
                return [start, end]
            }
        },
        {
            text: '昨天',
            value: () => {
                const start = new Date()
                const end = new Date()
                // 减去一天的毫秒数 (24小时 * 60分钟 * 60秒 * 1000毫秒)
                start.setTime(start.getTime() - 3600 * 1000 * 24)
                end.setTime(end.getTime() - 3600 * 1000 * 24)
                return [start, end]
            }
        },
        {
            text: '最近7天',
            value: () => {
                const start = new Date()
                const end = new Date()
                // 减去7天的毫秒数
                start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
                return [start, end]
            }
        },
        {
            text: '本月',
            value: () => {
                const start = new Date()
                const end = new Date()
                // 设置为本月第一天的开始时间
                start.setDate(1)
                start.setHours(0, 0, 0, 0)
                return [start, end]
            }
        },
        {
            text: '上月',
            value: () => {
                const start = new Date()
                const end = new Date()

                // 计算上月第一天
                start.setMonth(start.getMonth() - 1) // 月份减1
                start.setDate(1)                     // 设置为第一天
                start.setHours(0, 0, 0, 0)          // 设置为开始时间

                // 计算上月最后一天
                end.setMonth(end.getMonth() - 1 + 1) // 先减1再加1，相当于当前月
                end.setDate(0)                       // 设置为0，自动变为上月最后一天
                end.setHours(23, 59, 59, 999)       // 设置为结束时间

                return [start, end]
            }
        }
    ],

    /**
     * 视图组件模块映射缓存
     * 使用 Vite 的 import.meta.glob 预加载所有视图组件
     * 避免在运行时重复调用，提升性能
     *
     * @type {Object} 组件路径到加载函数的映射
     * @private
     */
    _viewModules: import.meta.glob('../views/**/*.vue'),

    /**
     * 检查指定路径的视图组件是否存在
     * 用于动态路由系统中验证组件文件是否存在
     *
     * @param {string} menuUrl - 菜单URL路径，如 '/StatsMgt/StatsChart'
     * @returns {boolean} 组件是否存在
     *
     * @example
     * TOOLS.checkViewExists('/StatsMgt/StatsChart')  // true
     * TOOLS.checkViewExists('/NonExistent/Page')     // false
     */
    checkViewExists(menuUrl) {
        const componentPath = `../views/${menuUrl}.vue`
        return componentPath in this._viewModules
    },

    /**
     * 获取视图组件的动态加载器函数
     * 支持懒加载和特殊优化（如图表页面的 ECharts 预加载）
     *
     * @param {string} menuUrl - 菜单URL路径
     * @returns {Function|null} 组件加载器函数或null
     *
     * @example
     * const loader = TOOLS.getViewLoader('/StatsMgt/StatsChart')
     * const component = await loader() // 异步加载组件
     */
    getViewLoader(menuUrl) {
        const componentPath = `../views/${menuUrl}.vue`

        // 对图表页面进行特殊优化：预加载 ECharts 工具
        // 这样可以减少图表页面的首次渲染时间
        if (menuUrl.includes('StatsChart') || menuUrl.includes('MarketStatsChart')) {
            return async () => {
                // 并行加载组件和 ECharts 工具，提升加载效率
                const [component] = await Promise.all([
                    this._viewModules[componentPath]?.(),  // 加载 Vue 组件
                    import('@/utils/echarts.js')           // 预加载 ECharts 工具
                ])
                return component
            }
        }

        // 普通页面直接返回加载器函数
        return this._viewModules[componentPath] || null
    },



    // ==================== 分页工具方法 ====================

    /**
     * 滚动到页面顶部
     * 自动查找正确的滚动容器并滚动到顶部
     * 主要用于分页切换后的用户体验优化
     *
     * @example
     * // 在分页切换后调用
     * TOOLS.scrollToTop()
     */
    scrollToTop() {
        // 查找主要内容滚动容器
        // 项目中使用 .content-wrapper 作为主要滚动容器
        const contentWrapper = document.querySelector('.content-wrapper')
        if (contentWrapper) {
            contentWrapper.scrollTop = 0 // 滚动到顶部
            return
        }

        // 如果没有找到主容器，可以在这里添加其他备选方案
        // 例如：document.documentElement.scrollTop = 0
    },

    /**
     * 创建标准化的分页处理器
     * 提供统一的分页操作方法，包括页码切换、页面大小变更、搜索重置等
     * 自动处理滚动到顶部、数据重新加载等常见需求
     *
     * @param {Object} pagination - 分页状态对象
     * @param {number} pagination.currentPage - 当前页码
     * @param {number} pagination.pageSize - 每页显示条数
     * @param {number} pagination.total - 总记录数
     *
     * @param {Object} form - 表单对象（可选）
     * @param {number} form.page_size - 表单中的页面大小字段，会与 pagination.pageSize 同步
     *
     * @param {Function} loadDataFn - 数据加载函数，在分页操作后自动调用
     *
     * @param {Object} options - 配置选项
     * @param {boolean} options.scrollToTopOnPageChange - 页码变化时是否滚动到顶部，默认 true
     * @param {boolean} options.resetPageOnSizeChange - 页面大小变化时是否重置到第一页，默认 true
     *
     * @returns {Object} 包含分页处理方法的对象
     *
     * @example
     * // 基本使用
     * const pagination = reactive({ currentPage: 1, pageSize: 10, total: 0 })
     * const { handleSizeChange, handleCurrentChange, handleSearch } =
     *   TOOLS.createPaginationHandlers(pagination, null, loadCustomerList)
     *
     * // 在模板中使用
     * <el-pagination
     *   @size-change="handleSizeChange"
     *   @current-change="handleCurrentChange"
     * />
     */
    createPaginationHandlers(pagination, form, loadDataFn, options = {}) {
        const {
            scrollToTopOnPageChange = true,  // 是否在页码变化时滚动到顶部
            resetPageOnSizeChange = true     // 是否在页面大小变化时重置页码
        } = options

        return {
            /**
             * 处理每页显示条数改变
             * Element Plus 分页组件的 size-change 事件处理器
             *
             * @param {number} size - 新的页面大小
             */
            handleSizeChange: async (size) => {
                pagination.pageSize = size

                // 同步表单中的页面大小字段（如果存在）
                if (form && form.page_size !== undefined) {
                    form.page_size = size
                }

                // 页面大小变化时通常重置到第一页
                if (resetPageOnSizeChange) {
                    pagination.currentPage = 1
                }

                // 重新加载数据
                await loadDataFn()

                // 滚动到顶部，提升用户体验
                if (scrollToTopOnPageChange) {
                    TOOLS.scrollToTop()
                }
            },

            /**
             * 处理当前页码改变
             * Element Plus 分页组件的 current-change 事件处理器
             *
             * @param {number} page - 新的页码
             */
            handleCurrentChange: async (page) => {
                pagination.currentPage = page

                // 重新加载数据
                await loadDataFn()

                // 滚动到顶部，让用户看到新页面的内容
                if (scrollToTopOnPageChange) {
                    TOOLS.scrollToTop()
                }
            },

            /**
             * 处理搜索操作
             * 搜索时重置到第一页并重新加载数据
             * 通常在搜索按钮点击时调用
             */
            handleSearch: async () => {
                pagination.currentPage = 1 // 搜索时重置到第一页

                // 重新加载数据
                await loadDataFn()

                // 滚动到顶部显示搜索结果
                if (scrollToTopOnPageChange) {
                    TOOLS.scrollToTop()
                }
            },

            /**
             * 页面大小变化处理（兼容性方法）
             * 兼容旧版本代码中使用的 changePage 方法名
             * 功能与 handleSizeChange 相同
             *
             * @param {number} size - 新的页面大小
             * @deprecated 建议使用 handleSizeChange
             */
            changePage: async (size) => {
                pagination.pageSize = size

                // 同步表单中的页面大小字段
                if (form && form.page_size !== undefined) {
                    form.page_size = size
                }

                // 重置到第一页
                if (resetPageOnSizeChange) {
                    pagination.currentPage = 1
                }

                // 重新加载数据
                await loadDataFn()

                // 滚动到顶部
                if (scrollToTopOnPageChange) {
                    TOOLS.scrollToTop()
                }
            }
        }
    }
}

/**
 * 导出工具函数对象
 *
 * 使用方式：
 * import TOOLS from '@/utils/tools'
 *
 * 或按需导入：
 * import { GetTime, Flaten } from '@/utils/tools'
 */
export default TOOLS